package com.itjin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.itjin.model.domain.entity.User;
import com.itjin.model.domain.entity.UserFollow;
import com.itjin.model.domain.vo.UserRegisterVO;
import com.itjin.model.domain.vo.UserVO;
import com.itjin.model.result.Result;
import com.itjin.service.UserService;
import com.itjin.utils.JwtUtil;
import com.itjin.mapper.UserMapper;
import com.itjin.mapper.UserFollowMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.itjin.contant.UserConstant.SALT;

/**
 * @author 胡
 * @description 针对表【user】的数据库操作Service实现
 * @createDate 2025-01-19 14:08:44
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserFollowMapper userFollowMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // 检查邮箱格式是否正确
    private static final String EMAIL_REGEX = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(\\.[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+)*@" +
            "([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}$";
    private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);

    public static boolean isValidEmail(String email) {
        if (email == null)
            return false;
        Matcher matcher = EMAIL_PATTERN.matcher(email);
        return matcher.matches();
    }

    @Override
    public Result<UserRegisterVO> userRegister(String userAccount, String email, String captcha, String userPassword,
            String checkPassword) {
        // 1. 校验所有字段是否为空
        if (StringUtils.isAllBlank(userAccount, userPassword, checkPassword, email, captcha)) {
            return Result.failure(400, "请输入完整信息");
        }

        // 2. 校验账户长度
        if (userAccount.length() < 4) {
            return Result.failure(400, "账号长度过短");
        }

        // 3.检查邮箱格式是否正确
        if (!isValidEmail(email)) {
            return Result.failure(400, "邮箱格式不正确");
        }

        // 检验验证码和Redis中储存的是否一致
        // 构造Redis键并获取存储的验证码
        String redisKey = "email:code:" + email.toLowerCase();
        String storedCode = (String) redisTemplate.opsForValue().get(redisKey);

        // 验证码检查
        if (storedCode == null) {
            return Result.failure(50001, "验证码已过期");
        }
        if (!storedCode.equals(captcha)) {
            return Result.failure(50001, "验证码错误");
        }

        // 4. 校验密码长度
        if (userPassword.length() < 8 || checkPassword.length() < 8) {
            return Result.failure(400, "密码长度不得小于8位");
        }

        // 5. 账户不能重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        long count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            return Result.failure(400, "当前账户已存在");
        }

        // 6. 账户不包含特殊字符
        String validPattern = "^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$";
        Pattern pattern = Pattern.compile(validPattern);
        Matcher matcher = pattern.matcher(userAccount);
        boolean matches = matcher.matches();
        if (!matches) {
            return Result.failure(400, "账户不得包含特殊字符");
        }

        // 7. 密码和校验密码是否相同
        if (!userPassword.equals(checkPassword)) {
            return Result.failure(400, "两次输入的密码不同，请检查");
        }

        // 8. 密码加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 9. 向用户数据库插入数据
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setEmail(email);
        boolean save = this.save(user);
        if (save) {
            UserRegisterVO userRegisterVO = UserRegisterVO.builder()
                    .id(user.getId())
                    .userAccount(user.getUserAccount())
                    .phone(user.getEmail())
                    .build();
            return Result.success(userRegisterVO);
        } else {
            return Result.failure(500, "用户注册失败");
        }

    }

    /**
     * 登录功能逻辑
     * 
     * @param loginIdentifier 用户账号或邮箱
     * @param userPassword    用户密码
     * @return 返回脱敏后的用户信息
     */
    @Override
    public User userLogin(String loginIdentifier, String userPassword) {
        // 1.校验
        if (StringUtils.isAllBlank(loginIdentifier, userPassword)) {
            throw new RuntimeException("账号/邮箱或密码不完整");
        }

        // 2.判断是账号还是邮箱
        boolean isEmail = isValidEmail(loginIdentifier);

        // 3.校验长度
        if (!isEmail && loginIdentifier.length() < 4) {
            throw new RuntimeException("账号长度过短");
        }

        // 4.校验密码
        if (userPassword.length() < 8) {
            throw new RuntimeException("密码长度过短");
        }

        // 5.账户不包含特殊字符 (仅当使用账号登录时校验)
        if (!isEmail) {
            String validPatten = "^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$";
            Pattern pattern = Pattern.compile(validPatten);
            Matcher matcher = pattern.matcher(loginIdentifier);
            boolean matches = matcher.matches();
            if (!matches) {
                throw new RuntimeException("账号不得包含特殊字符");
            }
        }

        // 6.密码加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 7.查询用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (isEmail) {
            queryWrapper.eq("email", loginIdentifier);
        } else {
            queryWrapper.eq("userAccount", loginIdentifier);
        }
        queryWrapper.eq("userPassword", encryptPassword);

        User user = userMapper.selectOne(queryWrapper);
        // 添加日志
        log.debug("从数据库查询到的用户信息: {}", user);

        if (user == null) {
            throw new RuntimeException("账号/邮箱或密码错误");
        }

        // 更新最后登录时间
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setLastLoginTime(new Date());
        userMapper.updateById(updateUser);

        // 用户脱敏
        User safetyUser = getSafetyUser(user);
        // 添加日志
        log.debug("脱敏后的用户信息: {}", safetyUser);

        return safetyUser;
    }

    // 用户脱敏
    @Override
    public User getSafetyUser(User user) {
        if (user == null) {
            return null;
        }
        User safetyUser = new User();
        safetyUser.setId(user.getId());
        safetyUser.setUsername(user.getUsername());
        safetyUser.setUserAccount(user.getUserAccount());
        safetyUser.setAvatar(user.getAvatar());
        safetyUser.setGender(user.getGender());
        safetyUser.setPhone(user.getPhone());
        safetyUser.setEmail(user.getEmail());
        safetyUser.setUserStatus(user.getUserStatus());
        safetyUser.setUserRole(user.getUserRole());
        safetyUser.setCreateTime(user.getCreateTime());
        safetyUser.setUpdateTime(user.getUpdateTime());
        safetyUser.setBiography(user.getBiography());
        safetyUser.setTags(user.getTags()); // 添加标签信息
        return safetyUser;
    }

    public String generateToken(User user) {
        return JwtUtil.generateToken(user.getUserAccount(), user.getUserRole());
    }

    /**
     * 关注用户
     * 
     * @param followerId 关注者ID
     * @param followedId 被关注者ID
     * @return 关注结果
     */
    @Override
    @Transactional
    public boolean followUser(Integer followerId, Integer followedId) {
        try {
            // 1. 参数校验
            if (followerId == null || followerId <= 0) {
                throw new IllegalArgumentException("关注者ID不合法");
            }
            if (followedId == null || followedId <= 0) {
                throw new IllegalArgumentException("被关注者ID不合法");
            }
            if (followerId.equals(followedId)) {
                throw new IllegalArgumentException("不能关注自己");
            }

            // 2. 检查两个用户是否存在
            User follower = userMapper.selectById(followerId);
            User followed = userMapper.selectById(followedId);
            if (follower == null || follower.getIsDelete() == 1) {
                throw new IllegalArgumentException("关注者不存在");
            }
            if (followed == null || followed.getIsDelete() == 1) {
                throw new IllegalArgumentException("被关注者不存在");
            }

            // 3. 检查当前关注状态
            QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("followerId", followerId)
                    .eq("followedId", followedId);
            UserFollow userFollow = userFollowMapper.selectOne(queryWrapper);

            boolean isNewFollow = false;
            if (userFollow == null) {
                // 新关注
                isNewFollow = true;
            } else if (userFollow.getStatus() == 0) {
                // 重新关注
                isNewFollow = true;
            } else {
                // 取消关注
                isNewFollow = false;
            }

            // 4. 执行关注/取消关注操作
            int rows = userFollowMapper.toggleFollow(followerId, followedId);

            // 5. 更新粉丝数和关注数
            if (rows > 0) {
                if (isNewFollow) {
                    // 增加被关注者的粉丝数
                    userFollowMapper.updateUserFans(followedId, 1);
                    // 增加关注者的关注数
                    userFollowMapper.updateUserFollows(followerId, 1);
                } else {
                    // 减少被关注者的粉丝数
                    userFollowMapper.updateUserFans(followedId, -1);
                    // 减少关注者的关注数
                    userFollowMapper.updateUserFollows(followerId, -1);
                }
            }

            return rows > 0;
        } catch (Exception e) {
            log.error("关注用户失败", e);
            throw new RuntimeException("关注用户失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户关注列表
     * 
     * @param userId 用户ID
     * @return
     */
    @Override
    public List<UserVO> getUserFollowList(Integer userId) {
        try {
            // 1. 参数校验
            if (userId == null || userId <= 0) {
                throw new IllegalArgumentException("用户ID不合法");
            }

            // 2. 查询用户关注列表
            QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("followerId", userId)
                    .eq("status", 1)
                    .orderByDesc("createTime");
            List<UserFollow> followList = userFollowMapper.selectList(queryWrapper);

            if (followList.isEmpty()) {
                return new ArrayList<>();
            }

            // 3. 获取所有被关注用户的ID
            List<Integer> followedIds = followList.stream()
                    .map(UserFollow::getFollowedId)
                    .collect(Collectors.toList());

            // 4. 批量查询被关注用户信息
            List<User> followedUsers = userMapper.selectBatchIds(followedIds);

            // 5. 转换为VO
            return followedUsers.stream()
                    .map(user -> UserVO.builder()
                            .id(user.getId())
                            .username(user.getUsername())
                            .userAccount(user.getUserAccount())
                            .avatar(user.getAvatar())
                            .gender(user.getGender())
                            .biography(user.getBiography())
                            .myFans(user.getMyFans())
                            .myFollows(user.getMyFollows())
                            .build())
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取关注列表失败", e);
            throw new RuntimeException("获取关注列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户粉丝列表
     * 
     * @param userId 用户ID
     * @return
     */
    @Override
    public List<UserVO> getUserFansList(Integer userId) {
        try {
            // 1. 参数校验
            if (userId == null || userId <= 0) {
                throw new IllegalArgumentException("用户ID不合法");
            }

            // 2. 查询用户粉丝列表
            QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("followedId", userId)
                    .eq("status", 1)
                    .orderByDesc("createTime");
            List<UserFollow> fansList = userFollowMapper.selectList(queryWrapper);

            if (fansList.isEmpty()) {
                return new ArrayList<>();
            }

            // 3. 获取所有粉丝用户的ID
            List<Integer> followerIds = fansList.stream()
                    .map(UserFollow::getFollowerId)
                    .collect(Collectors.toList());

            // 4. 批量查询粉丝用户信息
            List<User> followerUsers = userMapper.selectBatchIds(followerIds);

            // 5. 转换为VO
            return followerUsers.stream()
                    .map(user -> UserVO.builder()
                            .id(user.getId())
                            .username(user.getUsername())
                            .userAccount(user.getUserAccount())
                            .avatar(user.getAvatar())
                            .gender(user.getGender())
                            .biography(user.getBiography())
                            .myFans(user.getMyFans())
                            .myFollows(user.getMyFollows())
                            .build())
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取粉丝列表失败", e);
            throw new RuntimeException("获取粉丝列表失败: " + e.getMessage());
        }
    }

    /**
     * 取消关注用户
     * 
     * @param followerId 关注者ID
     * @param followedId 被关注者ID
     * @return 取消关注结果
     */
    @Override
    @Transactional
    public boolean unfollowUser(Integer followerId, Integer followedId) {
        try {
            // 1. 参数校验
            if (followerId == null || followerId <= 0) {
                throw new IllegalArgumentException("关注者ID不合法");
            }
            if (followedId == null || followedId <= 0) {
                throw new IllegalArgumentException("被关注者ID不合法");
            }

            // 2. 检查关注关系是否存在
            QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("followerId", followerId)
                    .eq("followedId", followedId)
                    .eq("status", 1);
            UserFollow userFollow = userFollowMapper.selectOne(queryWrapper);

            if (userFollow == null) {
                // 如果关注关系不存在或已经是取消状态，直接返回成功
                return true;
            }

            // 3. 更新关注状态为取消
            UserFollow updateFollow = new UserFollow();
            updateFollow.setId(userFollow.getId());
            updateFollow.setStatus(0);

            int rows = userFollowMapper.updateById(updateFollow);

            // 4. 更新粉丝数和关注数
            if (rows > 0) {
                // 减少被关注者的粉丝数
                userFollowMapper.updateUserFans(followedId, -1);
                // 减少关注者的关注数
                userFollowMapper.updateUserFollows(followerId, -1);
            }

            return rows > 0;
        } catch (Exception e) {
            log.error("取消关注用户失败", e);
            throw new RuntimeException("取消关注用户失败: " + e.getMessage());
        }
    }

    /**
     * 检查关注状态
     * 
     * @param followerId 关注者ID
     * @param followedId 被关注者ID
     * @return 关注状态
     */
    @Override
    public boolean checkFollowStatus(Integer followerId, Integer followedId) {
        try {
            // 1. 参数校验
            if (followerId == null || followerId <= 0) {
                throw new IllegalArgumentException("关注者ID不合法");
            }
            if (followedId == null || followedId <= 0) {
                throw new IllegalArgumentException("被关注者ID不合法");
            }
            if (followerId.equals(followedId)) {
                // 自己不能关注自己
                return false;
            }

            // 2. 查询关注关系
            QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("followerId", followerId)
                    .eq("followedId", followedId)
                    .eq("status", 1);

            // 3. 判断是否存在有效的关注关系
            return userFollowMapper.selectCount(queryWrapper) > 0;
        } catch (Exception e) {
            log.error("检查关注状态失败", e);
            throw new RuntimeException("检查关注状态失败: " + e.getMessage());
        }
    }

    @Override
    public boolean updateUserTags(Integer userId, List<String> tags) {

        // 检查标签数量是否超过5个
        if (tags != null && tags.size() > 5) {
            throw new RuntimeException("标签数量不能超过5个");
        }

        // 获取用户信息
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 更新标签信息
        user.setTags(tags);
        return updateById(user);
    }

    @Override
    public boolean resetPasswordByEmail(String email, String newPassword) {
        if (StringUtils.isBlank(email)) {
            throw new IllegalArgumentException("邮箱不能为空");
        }

        if (StringUtils.isBlank(newPassword)) {
            throw new IllegalArgumentException("新密码不能为空");
        }

        if (newPassword.length() < 8) {
            throw new IllegalArgumentException("密码长度不能小于8位");
        }

        // 查询用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            log.warn("尝试重置密码的邮箱不存在: {}", email);
            return false;
        }

        // 加密新密码
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + newPassword).getBytes());

        // 更新密码
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setUserPassword(encryptPassword);
        updateUser.setUpdateTime(new Date());

        int result = userMapper.updateById(updateUser);
        return result > 0;
    }

    @Override
    @Transactional
    public boolean addUserCoins(Integer userId, Integer coins) {
        // 1. 获取当前用户货币
        User user = userMapper.selectById(userId);
        if (user == null) {
            return false;
        }
        
        // 2. 计算新的货币数量
        Integer currentCoins = user.getMyCoins() != null ? user.getMyCoins() : 0;
        Integer newCoins = currentCoins + coins;

        // 3. 更新货币数量
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setMyCoins(newCoins);
        updateUser.setUpdateTime(new Date());

        int result = userMapper.updateById(updateUser);
        return result > 0;
    }
}
